home *** CD-ROM | disk | FTP | other *** search
- /* Sequence Grabber Lab
-
- This sample shows how to use a sequence grabber component to preview and record captured data.
- The example also demonstrates how to set up VideoBottlenecks and draw over top of captured data
- during the GrabFrameComplete callback.
- */
-
- #include "SequenceGrab.h"
-
- // globals
- // ------------------------
- BitMap screenBits;
- ICMAlignmentProcRecord apr;
-
- // functions
- // ------------------------
-
- // GrabFrameCompleteProc
- // This is where we draw text over the captured frame
- pascal ComponentResult GrabFrameCompleteProc(SGChannel sgChan, short nBufferNum, Boolean *pbDone, long lRefCon)
- {
- ComponentResult err = noErr;
-
- // call the default grab-complete function
-
- // Step 1.
- // Insert "SGGrabFrameComplete.clp" here
-
- // if the frame is done, draw some text over it
- if (*pbDone) {
- CGrafPtr pOldPort;
- CGrafPtr pTempPort = (CGrafPtr)lRefCon;
- GDHandle hghOldDevice;
- PixMapHandle hPixMap, hOldPixMap;
- Rect rectBuffer;
-
- // set to our temporary port
- GetGWorld(&pOldPort, &hghOldDevice);
- SetGWorld(pTempPort, NULL);
-
- // obtain information about a buffer that has
- // been passed to your callback function
-
- // Step 2.
- // Insert "SGGetBufferInfo.clp" here
-
- if (err == noErr) {
- // set up to draw into this buffer
- hOldPixMap = GetPortPixMap(pTempPort);
- SetPortPix(hPixMap);
-
- // draw some text into the buffer
- TextSize(10);
- TextMode(srcXor);
- MoveTo(rectBuffer.left + 5, rectBuffer.bottom - 5);
- DrawString("\pGrabFrameCompleteProc");
-
- // restore temporary port
- SetPortPix(hOldPixMap);
- }
-
- // restore old ports
- SetGWorld(pOldPort, hghOldDevice);
- }
-
- return err;
- }
-
- // SetupVideoBottlenecks
- // This function initializes the video bottleneck procedure so the sequence grabber
- // will call us when a frame has been captured. There are nine bottleneck procs.
- /* struct VideoBottles {
- short procCount;
- SGGrabBottleUPP grabProc;
- SGGrabCompleteBottleUPP grabCompleteProc;
- SGDisplayBottleUPP displayProc;
- SGCompressBottleUPP compressProc;
- SGCompressCompleteBottleUPP compressCompleteProc;
- SGAddFrameBottleUPP addFrameProc;
- SGTransferFrameBottleUPP transferFrameProc;
- SGGrabCompressCompleteBottleUPP grabCompressCompleteProc;
- SGDisplayCompressBottleUPP displayCompressProc;
- }
- */
- OSErr SetupVideoBottlenecks(SGChannel sgchanVideo, CGrafPtr pTempPort)
- {
- OSErr err = noErr;
-
- // set the value of a reference constant that is passed to the callback functions
- err = SGSetChannelRefCon(sgchanVideo, (long)pTempPort);
-
- if (err == noErr) {
- VideoBottles vb;
-
- // get the current bottlenecks
-
- // Step 1.
- // Insert "SGGetVideoBottlenecks.clp" here
-
- if (err == noErr) {
- RgnHandle theRgn = NewRgn();
-
- // add our GrabFrameComplete function
-
- // Step 2.
- // Insert "SGSetVideoBottlenecks" here
-
- // set up the temporary port with
- // a wide open visible and clip region...
- // so that you can use it in any video buffer
- SetRectRgn(theRgn, -32000, -32000, 32000, 32000);
- SetPortVisibleRegion(pTempPort, theRgn);
- SetPortClipRegion(pTempPort, theRgn);
-
- // tell QuickDraw about the changes
- PortChanged((GrafPtr)pTempPort);
-
- DisposeRgn(theRgn);
- }
- }
-
- return err;
- }
-
- // MakeSequenceGrabber
- // Open the default sequence graber component and initialize it
- SeqGrabComponent MakeSequenceGrabber(WindowPtr pMacWnd)
- {
- SeqGrabComponent seqGrab = NULL;
- long flags = 0;
- OSErr err = noErr;
-
- // open up the default sequence grabber
- seqGrab = OpenDefaultComponent(SeqGrabComponentType, 0);
-
- if (seqGrab != NULL) {
- // initialize the default sequence grabber component
-
- // Step 1.
- // Insert "SGInitialize.clp" here
-
- }
-
- if (err && (seqGrab != NULL)) {
- // clean up on failure
- CloseComponent(seqGrab);
- seqGrab = NULL;
- }
- return seqGrab;
- }
-
- // MakeSequenceGrabChannels
- // Create the new video and sound channels and set up the channel usage
- void MakeSequenceGrabChannels(SeqGrabComponent seqGrab, SGChannel *sgchanVideo, SGChannel *sgchanSound, const Rect *rect, Boolean bWillRecord)
- {
- long lUsage;
-
- OSErr err = noErr;
-
- // figure out the channel usage
- lUsage = seqGrabPreview; // always previewing by default
- if (bWillRecord)
- lUsage |= seqGrabRecord; // are we going to record?
-
- // create a video channel
-
- // Step 1.
- // Insert "SGNewChannel.clp" here
-
- if (err == noErr) {
- // set boundaries for new video channel
-
- // Step 2.
- // Insert "SGSetChannelBounds/Usage.clp" here
-
- if (err != noErr) {
- // clean up on failure
- SGDisposeChannel(seqGrab, *sgchanVideo);
- *sgchanVideo = NULL;
- }
- }
-
- // create a sound channel
- err = SGNewChannel(seqGrab, SoundMediaType, sgchanSound);
- if (err == noErr) {
- // set usage of new sound channel
- err = SGSetChannelUsage(*sgchanSound, lUsage);
-
- if (err != noErr) {
- // clean up on failure
- SGDisposeChannel(seqGrab, *sgchanSound);
- *sgchanSound = NULL;
- }
- }
- }
-
- OSErr DoRecord(SeqGrabComponent seqGrab)
- {
- FSSpec theFSSpec;
- Boolean isSelected, isReplacing;
- OSErr err = noErr;
-
- // Stop everything while the dialogs are up
-
- // Step 1.
- // Insert "SGStop.clp" here
-
- err = PutFile("\pSave new movie file as:", "\pSequenceGrab.mov", &theFSSpec, &isSelected, &isReplacing);
- if ((err = SGSetDataOutput(seqGrab, &theFSSpec, seqGrabToDisk)))
- goto bail;
-
- // Attempt to recover the preview area obscured by dialogs
- SGUpdate(seqGrab, 0);
-
- // Make the movie file
- DeleteMovieFile(&theFSSpec);
-
- // Step 2.
- // Insert "CreateMovieFile.clp here
-
- if (err) goto bail;
-
- FlushEvents(mDownMask+mUpMask,0);
-
- // Record!
-
- // Step 3.
- // Insert "SGStartRecord.clp" here
-
- if (err) goto bail;
-
- while (!Button() && (err == noErr))
- {
- // give time for record
- err = SGIdle(seqGrab);
- }
-
- FlushEvents(mDownMask+mUpMask,0);
-
- // If we recorded until we ran out of space, then allow SGStop to be
- // called to write the movie resource. The assumption here is that the
- // data output filled up but the disk has enough free space left to
- // write the movie resource.
- if (!((err == dskFulErr) || (err != eofErr))) {
- DeleteMovieFile(&theFSSpec);
- goto bail;
- }
-
- err = SGStop(seqGrab);
-
- bail:
-
- err = SGStartPreview(seqGrab);
-
- return err;
- }
-
- WindowRef MakeAWindow(void)
- {
- WindowPtr pMacWnd;
- Rect rectWnd = {0, 0, 230, 320}; //{0, 0, 480, 740};
- Rect rectBest;
-
- // figure out the best monitor for the window
- GetBestDeviceRect(NULL, &rectBest);
-
- // put the window in the top left corner of that monitor
- OffsetRect(&rectWnd, rectBest.left + 10, rectBest.top + 50);
-
- // create the window
- pMacWnd = NewCWindow(NULL, &rectWnd, "\pSequence Grabber",true, kWindowDocumentProc, (WindowPtr)-1,true, 0);
-
- // set the port to the new window
- SetPort(GetWindowPort(pMacWnd));
-
- return pMacWnd;
- }
-
- Boolean IsQuickTimeInstalled(void)
- {
- OSErr err;
- long lResult;
-
- err = Gestalt(gestaltQuickTime, &lResult);
- return (err == noErr);
- }
-
- void main(void)
- {
- WindowRef pMacWnd;
- CGrafPtr pTempPort;
- SeqGrabComponent seqGrab;
- SGChannel sgchanVideo, sgchanSound;
- Rect thePortRect;
- Boolean bDone = false;
-
- OSErr err = noErr;
-
- // initialize for carbon & QuickTime
- InitCursor();
- if ( IsQuickTimeInstalled() )
- EnterMovies();
- else
- goto bail;
-
- GetQDGlobalsScreenBits( &screenBits );
-
- // create a window
- pMacWnd = MakeAWindow();
-
- // Step 1.
- // Build MakeSequenceGrabber function
-
- // create a sequence grabber
- seqGrab = MakeSequenceGrabber(pMacWnd);
- if (seqGrab == NULL)
- return;
-
- // Step 2.
- // Build MakeSequenceGrabChannels function
-
- // create the grab channels
- GetPortBounds(GetWindowPort(pMacWnd), &thePortRect);
- MakeSequenceGrabChannels(seqGrab, &sgchanVideo, &sgchanSound, &thePortRect, true); // true = recording
-
- // Step 3.
- // Build SetupVideoBottlenecks function
-
- // set up a video bottleneck
- // create a temporary port for drawing...
- pTempPort = CreateNewPort();
- if (sgchanVideo != NULL) {
- err = SetupVideoBottlenecks(sgchanVideo, pTempPort);
- }
-
- // start the sequence grabber preview
-
- // Step 4.
- // Insert "SGStartPreview.clp" here
-
- if (err) goto bail;
-
- while (!bDone) {
- short nPart;
- WindowRef pWhichWnd;
- EventRecord er;
-
- GetNextEvent(everyEvent, &er);
-
- switch (er.what) {
- case nullEvent:
- // give the sequence grabber time
-
- // Step 5.
- // Insert "SGIdle.clp" here
-
- if (err != noErr)
- bDone = true;
- break;
-
- case updateEvt:
- if (er.message == (long)pMacWnd) {
- RgnHandle updateRgn = NewRgn();
-
- GetWindowRegion(pMacWnd, kWindowUpdateRgn, updateRgn);
-
- // inform the sequence grabber of the update
- // Step 6.
- // Insert "SGUpdate.clp" here
-
- // and swallow the update event
- BeginUpdate(pMacWnd);
- EndUpdate(pMacWnd);
-
- DisposeRgn(updateRgn);
- }
- break;
-
- case mouseDown:
- nPart = FindWindow(er.where, &pWhichWnd);
- if (pWhichWnd == pMacWnd) {
- switch (nPart) {
- case inContent:
- if ( er.modifiers & cmdKey ) {
-
- // Step 7.
- // Build DoRecord function
-
- DoRecord( seqGrab );
- break;
- }
-
- // pause until mouse button is released
- SGPause(seqGrab, true);
- while (StillDown())
- ;
- SGPause(seqGrab, false);
- break;
-
- case inGoAway:
- bDone = TrackGoAway(pMacWnd, er.where);
- break;
-
- case inDrag:
- if (StillDown()) {
- // pause when dragging window so video
- // doesn't draw in the wrong place
-
- // Step 8.
- // Insert SGPause.clp here
-
- }
- break;
-
- } // switch
- }
- break;
-
- } // switch
- } // while
-
- bail:
-
- // clean up
- if ( seqGrab ) {
- SGStop(seqGrab);
- CloseComponent(seqGrab);
- }
- if ( pMacWnd )
- DisposeWindow(pMacWnd);
- }